//! 格式化输出至framebuffer，部分参考bootloader实现

use bootloader_api::info::FrameBuffer;
use core::fmt;
use core::fmt::Write;
use spin::{Mutex, Once};
use x86_64::instructions::interrupts;

/// FrameBuffer驱动全局变量
pub static FRAME_BUFFER: Once<Mutex<FrameBufferDriver>> = Once::new();

/// 初始化FrameBuffer驱动
pub fn init<'a>(frame_buffer: &'a mut FrameBuffer) {
    serial_println!("[Kernel] {:#x?}", frame_buffer);

    // 根据BootInfo传入信息创建FrameBuffer驱动
    FRAME_BUFFER.call_once(|| Mutex::new(FrameBufferDriver::new(frame_buffer)));
}

/// 辅助打印结构，主要实现Write trait
struct Printer;
impl Write for Printer {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        interrupts::without_interrupts(|| {
            FRAME_BUFFER
                .get()
                .and_then(|fb| Some(fb.lock().write_str(s)))
                .expect("Uninit frame buffer");
        });
        Ok(())
    }
}

/// 打印至FrameBuffer
pub fn print(args: fmt::Arguments) {
    // write_fmt函数在Write trait中定义，因此需要实现Write trait
    Printer.write_fmt(args).unwrap();
}

/// 格式化打印至FrameBuffer（无换行）
#[macro_export]
macro_rules! fb_print {
    ($($arg:tt)*) => {
        $crate::driver::fb::print(format_args!($($arg)*))
    };
}

/// 格式化打印至FrameBuffer（有换行）
#[macro_export]
macro_rules! fb_println {
    () => ($crate::fb_print!("\n"));
    ($fmt:expr) => ($crate::fb_print!(concat!($fmt, "\n")));
    ($fmt:expr, $($arg:tt)*) => ($crate::fb_print!(
        concat!($fmt, "\n"), $($arg)*));
}

/// FrameBuffer驱动
pub struct FrameBufferDriver {
    // TODO：设计结构体需要的成员
}

// TODO：设计结构体需要的接口，至少应包括new和write_str（前面的代码调用过）
impl FrameBufferDriver {
    /// 创建FrameBuffer驱动
    pub fn new<'a>(_framebuffer: &'a mut FrameBuffer) -> Self {
        // TODO：新建FrameBuffer驱动
        Self {}
    }

    /// 写字符串
    pub fn write_str(&mut self, _s: &str) {
        // TODO
    }
}
